package cn.android.basic.components.span

import android.content.res.Resources
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.style.*
import android.util.TypedValue
import android.view.View
import androidx.core.content.res.ResourcesCompat
import cn.android.basic.resources

/**
 * createBy Eshel
 * <br>createTime: 2019/6/18 15:53
 * <br>desc: SpannableString 工具
 * <br>使用方法: [spannerExample]
 */

private fun spannerExample() {
    Spanner.with()
        .append("哈哈哈")
        .append("哈哈哈") {
            size(18)
            color(Color.RED)
            style(Typeface.BOLD)
            underline()
            strikethrough()
            click {
                print("hahaha")
            }
        }
        .image(android.R.mipmap.sym_def_app_icon)
        .end()
}

class Spanner private constructor(private val sb: SpannableStringBuilder) : IEndSpanner, TextBuilder {

    private var child: SpannableString? = null

    companion object {
        /**
         * 根据传入的富文本创建 SpanHelper, 后续拼接操作将在该富文本后进行(保留传入的富文本)
         *
         * @param sb 传入的富文本, 保留其富文本属性
         */
        fun with(sb: SpannableStringBuilder): IEndSpanner {
            return Spanner(sb)
        }

        /**
         * 传入一个普通字符串, 保留此字符串(无富文本属性), 并且该字符串在最前面
         *
         * @param text SpanHelper不会处理此字符串
         */
        fun with(text: CharSequence?): IEndSpanner {
            return Spanner(SpannableStringBuilder(text))
        }

        fun with(): IEndSpanner {
            return Spanner(SpannableStringBuilder(""))
        }
    }

    /**
     * @return 返回拼接好的字符串
     */
    override fun end(): SpannableStringBuilder {
        return sb
    }

    override fun append(text: CharSequence?): IEndSpanner {
        sb.append(text)
        return this
    }

    /**
     * 不做特殊处理, 直接拼接至富文本中
     */
    override fun append(text: Int): IEndSpanner {
        sb.append(text.toString())
        return this
    }

    override fun append(text: Char): IEndSpanner {
        sb.append(text)
        return this
    }

    override fun append(text: Float): IEndSpanner {
        sb.append(text.toString())
        return this
    }

    /**
     * 创建一个文本拼接对象, 此后对文本设置字号, 颜色等都只会对传入 text 生效
     *
     * @param text 进行字号, 颜色设置的目标文本
     */
    override fun append(text: CharSequence?, block: TextBuilder.() -> Unit): IEndSpanner {
        child = SpannableString(text)
        block.invoke(this)
        sb.append(child)
        child = null
        return this
    }

    override fun image(resId: Int): IEndSpanner {
        val drawable = ResourcesCompat.getDrawable(resources(), resId, null)
        setImage(drawable, -1, -1)
        return this
    }

    override fun image(resId: Int, height: Int): IEndSpanner {
        val drawable = ResourcesCompat.getDrawable(resources(), resId, null)
        setImage(drawable, -1, height)
        return this
    }

    override fun imageByWidth(resId: Int, width: Int): IEndSpanner {
        val drawable = ResourcesCompat.getDrawable(resources(), resId, null)
        setImage(drawable, width, -1)
        return this
    }

    override fun color(color: Int) {
        child?.run {
            setSpan(ForegroundColorSpan(color), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    }

    override fun size(unit: Int, size: Int) {
        child?.run {
            setSpan(
                AbsoluteSizeSpan(TypedValue.applyDimension(unit, size.toFloat(), Resources.getSystem().displayMetrics).toInt()),
                0,
                length,
                Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
            )
        }
    }

    override fun underline() {
        child?.run { setSpan(UnderlineSpan(), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) }
    }

    override fun click(listener: ClickableSpan?) {
        child?.run {
            setSpan(listener, 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    }

    override fun click(listener: (widget: View) -> Unit) {
        child?.run {
            setSpan(object : ClickableSpan(){
                override fun onClick(widget: View) {
                    listener.invoke(widget)
                }
            }, 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    }

    override fun style(textStyle: Int) {
        child?.run {
            //flag 前面后面都不包括的意思;
            setSpan(StyleSpan(textStyle), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
        }
    }

    override fun strikethrough() {
        child?.run { setSpan(StrikethroughSpan(), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE) }
    }

    /**
     * 设置图片
     * 注意: 私有方法, 请勿修改, 请使用对外提供的方法
     * [.image]
     * [Spanner#image(int, int), Spanner#imageByWidth(int, int)][Spanner.image]
     */
    private fun setImage(drawable: Drawable?, w: Int, h: Int) {
        if(drawable == null) return
        var width = w
        var height = h
        val intrinsicHeight = drawable.intrinsicHeight
        val intrinsicWidth = drawable.intrinsicWidth
        if (width > 0 && height <= 0) {
            height = width * intrinsicHeight / intrinsicWidth
        } else if (width <= 0 && height > 0) {
            width = height * intrinsicWidth / intrinsicHeight
        } else if (width <= 0 && height <= 0) {
            width = intrinsicWidth
            height = intrinsicHeight
        }
        drawable.setBounds(0, 0, width, height)
        val span = ImageSpan(drawable, ImageSpan.ALIGN_BASELINE)
        val ss = SpannableString("\uFFFC")
        ss.setSpan(span, 0, child!!.length, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        sb.append(ss)
    }
}